#!/bin/bash
set -e

TOP_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." &> /dev/null && pwd )"
SCRIPTS_DIR="${TOP_DIR}/scripts"
PACKAGE_HARVESTER_OS_DIR="${TOP_DIR}/package/harvester-os"
PACKAGE_HARVESTER_REPO_DIR="${TOP_DIR}/package/harvester-repo"
: ${RKE2_IMAGE_REPO:=https://github.com/rancher/rke2/releases/download/}

cd ${TOP_DIR}

source ${SCRIPTS_DIR}/version
source ${SCRIPTS_DIR}/version-rke2
source ${SCRIPTS_DIR}/version-rancher
source ${SCRIPTS_DIR}/lib/http
source ${SCRIPTS_DIR}/lib/image
source ${SCRIPTS_DIR}/hack/patch-rancher-monitoring
source ${SCRIPTS_DIR}/hack/patch-rancher-logging
source ${SCRIPTS_DIR}/hack/patch-rancher-monitoring-crd

BUNDLE_DIR="${PACKAGE_HARVESTER_OS_DIR}/iso/bundle"
CHARTS_DIR="${PACKAGE_HARVESTER_REPO_DIR}/charts"
IMAGES_DIR="${BUNDLE_DIR}/harvester/images"
IMAGES_LISTS_DIR="${BUNDLE_DIR}/harvester/images-lists"
RANCHERD_IMAGES_DIR="${BUNDLE_DIR}/rancherd/images"
VM_IMPORT_CONTROLLER_CHART_VERSION="0.1.7"
VM_IMPORT_CONTROLLER_IMAGE="rancher/harvester-vm-import-controller:v0.1.7"
PCIDEVICES_CONTROLLER_CHART_VERSION="0.3.2"
PCIDEVICES_CONTROLLER_IMAGE="rancher/harvester-pcidevices:v0.3.2"
HARVESTER_SEEDER_CHART_VERSION="0.1.1"
HARVESTER_SEEDER_IMAGE="rancher/harvester-seeder:v0.1.1"
NVIDIA_DRIVER_RUNTIME_CHART_VERSION="0.1.1"
mkdir -p ${CHARTS_DIR}
mkdir -p ${IMAGES_DIR}
mkdir -p ${IMAGES_LISTS_DIR}
mkdir -p ${RANCHERD_IMAGES_DIR}

# Prepare Harvester chart
harvester_path=../harvester
if [ ! -d ${harvester_path} ];then
    echo "No existed harvester source. Pulling into /tmp/harvester"
    git clone --branch master --single-branch --depth 1 https://github.com/harvester/harvester.git /tmp/harvester
    harvester_path=/tmp/harvester
fi

# Revert harvester chart version patch to clean dirty git status
reset_charts() {
  pushd ${harvester_path}
  git checkout -- ./deploy/charts
  popd
}

# This must be placed after cloning `harvester/harvester`` in case `make build-bundle` is run directly.
source ${SCRIPTS_DIR}/version-harvester ${TOP_DIR}/../harvester

# Replace harvester chart version
${SCRIPTS_DIR}/patch-harvester ${TOP_DIR}/../harvester
# Package harvester chart
harvester_chart_path=${harvester_path}/deploy/charts/harvester
harvester_crd_chart_path=${harvester_path}/deploy/charts/harvester-crd
helm package ${harvester_chart_path} -d ${CHARTS_DIR}
helm package ${harvester_crd_chart_path} -d ${CHARTS_DIR}

# Prepare monitoring chart
source ${SCRIPTS_DIR}/version-monitoring
helm pull https://charts.rancher.io/assets/rancher-monitoring-crd/rancher-monitoring-crd-${MONITORING_VERSION}.tgz -d ${CHARTS_DIR}
helm pull https://charts.rancher.io/assets/rancher-monitoring/rancher-monitoring-${MONITORING_VERSION}.tgz -d ${CHARTS_DIR}

# patch rancher-monitoring chart to fix issues
PKG_PATCH_MONITORING_PATH="${TOP_DIR}/pkg/config/templates/patch/rancher-monitoring"
patch_rancher_monitoring_chart ${CHARTS_DIR} ${MONITORING_VERSION} ${PKG_PATCH_MONITORING_PATH}

# patch rancher-monitoring-crd chart to fix issues
PKG_PATCH_MONITORING_CRD_PATH="${TOP_DIR}/pkg/config/templates/patch/rancher-monitoring-crd"
patch_rancher_monitoring_crd_chart ${CHARTS_DIR} ${MONITORING_VERSION} ${PKG_PATCH_MONITORING_CRD_PATH}

# make chart sanity check
tar zxvf ${CHARTS_DIR}/rancher-monitoring-crd-${MONITORING_VERSION}.tgz >/dev/null --warning=no-timestamp
tar zxvf ${CHARTS_DIR}/rancher-monitoring-${MONITORING_VERSION}.tgz >/dev/null --warning=no-timestamp

# Prepare logging chart
source ${SCRIPTS_DIR}/version-logging
helm pull https://charts.rancher.io/assets/rancher-logging-crd/rancher-logging-crd-${LOGGING_VERSION}.tgz -d ${CHARTS_DIR}
helm pull https://charts.rancher.io/assets/rancher-logging/rancher-logging-${LOGGING_VERSION}.tgz -d ${CHARTS_DIR}

# make chart sanity check
tar zxvf ${CHARTS_DIR}/rancher-logging-crd-${LOGGING_VERSION}.tgz >/dev/null  --warning=no-timestamp
tar zxvf ${CHARTS_DIR}/rancher-logging-${LOGGING_VERSION}.tgz >/dev/null --warning=no-timestamp

# patch rancher-logging chart to collect more logs"
PKG_PATCH_LOGGING_PATH="${TOP_DIR}/pkg/config/templates/patch/rancher-logging"
patch_rancher_logging_chart ${CHARTS_DIR} ${LOGGING_VERSION} ${PKG_PATCH_LOGGING_PATH}

# make chart sanity check again after patch
tar zxvf ${CHARTS_DIR}/rancher-logging-${LOGGING_VERSION}.tgz >/dev/null --warning=no-timestamp

# Prepare vm-import-controller-chart
helm pull https://github.com/harvester/charts/releases/download/harvester-vm-import-controller-${VM_IMPORT_CONTROLLER_CHART_VERSION}/harvester-vm-import-controller-${VM_IMPORT_CONTROLLER_CHART_VERSION}.tgz -d ${CHARTS_DIR}
# make chart sanity check
tar zxvf ${CHARTS_DIR}/harvester-vm-import-controller-${VM_IMPORT_CONTROLLER_CHART_VERSION}.tgz >/dev/null --warning=no-timestamp

# Prepare pcidevices-chart
helm pull https://github.com/harvester/charts/releases/download/harvester-pcidevices-controller-${PCIDEVICES_CONTROLLER_CHART_VERSION}/harvester-pcidevices-controller-${PCIDEVICES_CONTROLLER_CHART_VERSION}.tgz -d ${CHARTS_DIR}
# make chart sanity check
tar zxvf ${CHARTS_DIR}/harvester-pcidevices-controller-${PCIDEVICES_CONTROLLER_CHART_VERSION}.tgz >/dev/null --warning=no-timestamp

# Prepare harvester-seeder-chart
helm pull https://github.com/harvester/charts/releases/download/harvester-seeder-${HARVESTER_SEEDER_CHART_VERSION}/harvester-seeder-${HARVESTER_SEEDER_CHART_VERSION}.tgz -d ${CHARTS_DIR}
# make chart sanity check
tar zxvf ${CHARTS_DIR}/harvester-seeder-${HARVESTER_SEEDER_CHART_VERSION}.tgz >/dev/null --warning=no-timestamp

# Prepare nvidia-driver-toolkit chart
helm pull https://github.com/harvester/charts/releases/download/nvidia-driver-runtime-${NVIDIA_DRIVER_RUNTIME_CHART_VERSION}/nvidia-driver-runtime-${NVIDIA_DRIVER_RUNTIME_CHART_VERSION}.tgz -d ${CHARTS_DIR}
# make chart sanity check
tar zxvf ${CHARTS_DIR}/nvidia-driver-runtime-${NVIDIA_DRIVER_RUNTIME_CHART_VERSION}.tgz >/dev/null --warning=no-timestamp

# Create Helm repo index after charts are ready
helm repo index ${CHARTS_DIR}

# Use offline bundle cache
if [ -n "$HARVESTER_INSTALLER_OFFLINE_BUILD" -a -e /bundle ]; then
  cp -rf /bundle/* ${BUNDLE_DIR}/
  reset_charts
  exit 0
fi

# Rancherd bootstrap images
image_list_file=${RANCHERD_IMAGES_DIR}/rancherd-bootstrap-images-${VERSION}.txt
cp ${SCRIPTS_DIR}/images/rancherd-bootstrap-images.txt $image_list_file
RKE2_VERSION_NORMALIZED=${RKE2_VERSION/+/-} # v1.21.3-rc6+rke2r2 -> v1.21.3-rc6-rke2r2
sed -i "s,\$RKE2_VERSION,${RKE2_VERSION_NORMALIZED}," ${image_list_file}
save_image "agent" $BUNDLE_DIR ${image_list_file} ${RANCHERD_IMAGES_DIR}

# Rancher images
image_list_file=${IMAGES_LISTS_DIR}/rancher-images-${RANCHER_VERSION}.txt
cp ${SCRIPTS_DIR}/images/rancher-images.txt $image_list_file
save_image "common" $BUNDLE_DIR $image_list_file ${IMAGES_DIR}

# RKE2 images
RKE2_IMAGES_URL="${RKE2_IMAGE_REPO}${RKE2_VERSION}"
image_list_file="${IMAGES_LISTS_DIR}/rke2-images.linux-amd64-${RKE2_VERSION_NORMALIZED}.txt"
image_archive="${IMAGES_DIR}/rke2-images.linux-amd64-${RKE2_VERSION_NORMALIZED}.tar.zst"
get_url "${RKE2_IMAGES_URL}/rke2-images.linux-amd64.txt" $image_list_file
get_url "${RKE2_IMAGES_URL}/rke2-images.linux-amd64.tar.zst" $image_archive
add_image_list_to_metadata "rke2" $BUNDLE_DIR $image_list_file $image_archive

# exclude SR-IOV images
image_list_file="${IMAGES_LISTS_DIR}/rke2-images-multus.linux-amd64-${RKE2_VERSION_NORMALIZED}.txt"
save_image_list "rke2-images-multus" "${RKE2_IMAGES_URL}/rke2-images-multus.linux-amd64.txt" $image_list_file

save_image "rke2" $BUNDLE_DIR $image_list_file ${IMAGES_DIR}

# Harvester images: get image list from harvester chart's values file
image_list_file="harvester-images-${VERSION}.txt"
values_file="${harvester_chart_path}/values.yaml"
touch ${image_list_file}
repositories=( $(yq eval ' explode(.) | .. | select(has("repository")) |select(has("tag")) | .repository' ${values_file}) )
tags=( $(yq eval ' explode(.) | .. | select(has("repository")) |select(has("tag")) | .tag' ${values_file}) )
repositories_length=${#repositories[@]}
tags_length=${#tags[@]}
if [ ${repositories_length} -ne ${tags_length} ];then
  echo "The number of image repositories does not match the number of image tags";
  exit 1
fi
for i in "${!repositories[@]}"; do
  echo "${repositories[$i]}:${tags[$i]}">>${image_list_file}
done

# vm-import-controller: get images from values.yaml
echo ${VM_IMPORT_CONTROLLER_IMAGE} >>  ${image_list_file}
# pcidevices-controller images
echo ${PCIDEVICES_CONTROLLER_IMAGE} >> ${image_list_file}

# seeder images
echo ${HARVESTER_SEEDER_IMAGE} >> ${image_list_file}

# harvester additional images, which is not in rancher images, not in harvester images or any others
# do not add any comment line into this file, each line should be an valid image name
cat ${SCRIPTS_DIR}/images/harvester-additional-images.txt >> ${image_list_file}

# get longhorn image list
longhorn_version=v$(ls ${harvester_chart_path}/charts | grep longhorn| sed -e "s/^longhorn-//" -e "s/.tgz$//")
longhorn_image_url=https://raw.githubusercontent.com/longhorn/longhorn/${longhorn_version}/deploy/longhorn-images.txt
curl ${longhorn_image_url}>>${image_list_file}

# format image list
awk -F ':' '{if($2==""){print $1":latest"}else{print $0}}' "${image_list_file}" | \
awk -F '/' '{if(NF>=3){print $0} else if(NF==2){print "docker.io/"$0}else if(NF==1){print "docker.io/library/"$0}}' >"${image_list_file}.tmp"

# clean image list
sort -u "${image_list_file}.tmp" | \
grep -Ev "local-path-provisioner|library-traefik|klipper-lb|multus" >"${image_list_file}"

cp ${image_list_file} ${IMAGES_LISTS_DIR}
save_image "common" $BUNDLE_DIR ${IMAGES_LISTS_DIR}/${image_list_file} ${IMAGES_DIR}

# Tag harvester-upgrade:master-head to harvester-upgrade:<version> and save the image to an archive
# This makes it possible to upgrade a cluster with a master ISO.
# Also tag harvester-upgrade:master-head to harvester-upgrade:master-<commit>-head and save the image to an archive
# This makes it possible to upgrade from master builds to master builds
upgrade_image_repo=$(yq -e e '.upgrade.image.repository' $values_file)
upgrade_image_tag=$(yq -e e '.upgrade.image.tag' $values_file)
if [ "$upgrade_image_tag" != "$HARVESTER_VERSION" ]; then
  docker tag "${upgrade_image_repo}:${upgrade_image_tag}" "rancher/harvester-upgrade:${HARVESTER_VERSION}"
  docker tag "${upgrade_image_repo}:${upgrade_image_tag}" "rancher/harvester-upgrade:${HARVESTER_APP_VERSION}-head"
  image_list_file="${IMAGES_LISTS_DIR}/harvester-extra-${VERSION}.txt"
  image_archive="${IMAGES_DIR}/harvester-extra-${VERSION}.tar"
  echo "docker.io/rancher/harvester-upgrade:${HARVESTER_VERSION}" > ${image_list_file}
  echo "docker.io/rancher/harvester-upgrade:${HARVESTER_APP_VERSION}-head" >> ${image_list_file}
  docker image save -o $image_archive $(<$image_list_file)
  zstd --rm $image_archive -o "${image_archive}.zst"
  add_image_list_to_metadata "common" $BUNDLE_DIR $image_list_file "${image_archive}.zst"
fi

reset_charts
